/*
 * TCSS 422 Web Spider Project
 * Group Money: Al McKenzie, Michael Pitts, Taylor Zielske
 */

package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Collection;
import java.util.HashSet;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.border.BevelBorder;
import javax.swing.filechooser.FileNameExtensionFilter;

import control.UserSettings;

/**
 * This class presents the user with a variety of options that allow them to dictate 
 * how the web spider will collect data from the web.
 * 
 * @author Taylor Zielske
 * @version Nov 9, 2011
 */
public class StartGUI {
	/**
	 * The start URLs
	 */
	private static Collection<String> my_seeds;
	/**
	 * The number of sites to visit
	 */
	private static int my_maxsites;
	/**
	 * The array of number of threads to use, null if single threaded
	 */
	private static int[] my_numthreads;
	/**
	 * The terms to search
	 */
	private static Collection<String> my_searchterms;
	/**
	 * The links to not visit
	 */
	private static Collection<String> my_bannedlinks;
	/**
	 * How to output the results, GUI, Console, or File
	 */
	private static PrintStream[] my_printstreams;
	/**
	 * The frame
	 */
	private JFrame my_frame;
	/**
	 * The panel
	 */
	private JPanel my_panel;
	/**
	 * The text field to enter the seed urls, comma seperated
	 */
	private JTextField my_seeds_text;
	/**
	 * The text field to enter the number of sites to vist
	 */
	private JTextField my_max_sites_text;
	/**
	 * The text field to enter the terms, comma seperated
	 */
	private JTextField my_search_terms_text;
	/**
	 * The text field to enter the banned links, comma seperated
	 */
	private JTextField my_banned_links_text;
	/**
	 * The start button
	 */
	private JButton my_start;
	/**
	 * The text field to enter the number of threads to load
	 */
	private JTextField load;
	/**
	 * The text field to enter the number of threads to parse
	 */
    private JTextField parse;
    /**
     * Sets single threaded
     */
    private JRadioButton single;
    /**
     * Sets multi-threaded
     */
    private JRadioButton multi;
    /**
     * Sets multi-threaded load & parse
     */
    private JRadioButton loadparse;
    /**
     * The button that opens the JFileChooser
     */
    private JButton filepath;
    /**
     * Sets output to file
     */
    private JCheckBox file;
    /**
     * Sets output to console
     */
    private JCheckBox console;
    /**
     * Set to true when start button is pressed, initially false
     */
    private boolean startpressed;
    /**
     * The text field to enter the number of threads to use
     */
    private JTextField multithread;
    /**
     * Sets output to console
     */
    private JCheckBox my_gui;
    /**
     * The file name specified
     */
    private File filename;
    /**
     * The frequency to output to console
     */
    private int my_frequency;
    /**
     * The text field to enter the frequency
     */
    private JTextField freq;
	/**
	 * Constructs a new Start GUI that will use the settings passed to it as the 
	 * default settings when initialized.
	 * @param the_default_settings are the settings the controls should default to
	 * on start-up.
	 */
	public StartGUI(final UserSettings the_default_settings) {
		my_seeds= new HashSet<String>();
		my_seeds.addAll(the_default_settings.getSeeds());
		my_maxsites = the_default_settings.getMaxSites();
		my_numthreads = the_default_settings.getNumberThreads();
		my_searchterms = new HashSet<String>();
		my_searchterms.addAll(the_default_settings.getSearchTerms());
		my_bannedlinks = new HashSet<String>();
		my_bannedlinks.addAll(the_default_settings.getBannedLinks());
		my_printstreams = the_default_settings.getPrintStreams();
		my_frequency = the_default_settings.getUpdateFrequency();
		startpressed = false;
	}
	/**
	 * Starts the GUI to collect user settings.
	 */
	public void start() {
		my_frame = new JFrame();
		my_panel = new JPanel();
		my_panel.setLayout(new BoxLayout(my_panel, BoxLayout.PAGE_AXIS));
		//seed
		JPanel seedpanel = new JPanel(new BorderLayout());
		JLabel seedstart = new JLabel(" The seed URL's:");
		JLabel seedend = new JLabel("(comma seperated) ");
	    my_seeds_text = new JTextField(my_seeds.toString().substring(1, my_seeds.toString().length() -1));
	    seedpanel.add(seedstart, BorderLayout.WEST);
	    seedpanel.add(my_seeds_text, BorderLayout.CENTER);
	    seedpanel.add(seedend, BorderLayout.EAST);
	    //banned
		JPanel bannedpanel = new JPanel(new BorderLayout());
		JLabel bannedstart = new JLabel(" The banned URL's:");
		JLabel bannedend = new JLabel("(comma seperated) ");
	    my_banned_links_text = new JTextField(my_bannedlinks.toString().substring(1, my_bannedlinks.toString().length() -1));
	    bannedpanel.add(bannedstart, BorderLayout.WEST);
	    bannedpanel.add(my_banned_links_text, BorderLayout.CENTER);
	    bannedpanel.add(bannedend, BorderLayout.EAST);
	    //search terms
		JPanel searchtermspanel = new JPanel(new BorderLayout());
		JLabel ststart = new JLabel(" The keywords:");
		JLabel stend = new JLabel("(comma seperated) ");
	    my_search_terms_text = new JTextField(my_searchterms.toString().substring(1, my_searchterms.toString().length() -1));
	    searchtermspanel.add(ststart, BorderLayout.WEST);
	    searchtermspanel.add(my_search_terms_text, BorderLayout.CENTER);
	    searchtermspanel.add(stend, BorderLayout.EAST);
	    //max sites
		JPanel maxpanel = new JPanel(new BorderLayout());
		JLabel maxstart = new JLabel(" The maximum number of sites to visit:");
	    my_max_sites_text = new JTextField();
	    my_max_sites_text.setText(Integer.toString(my_maxsites));
	    maxpanel.add(maxstart, BorderLayout.WEST);
	    maxpanel.add(my_max_sites_text, BorderLayout.CENTER);
	    //threads
		ButtonGroup threads = new ButtonGroup();
	    single = new JRadioButton("Single");
	    single.setSelected(true);
	    multi = new JRadioButton("Multiple     Total:");
	    threads.add(single);
	    threads.add(multi);
	    JPanel threadpanel = new JPanel(new BorderLayout());
		JLabel threadstart = new JLabel(" THREADS");
	    threadstart.setFont(new Font("SansSerif", Font.BOLD, 14));
	    threadstart.setForeground(Color.DARK_GRAY);
	    load = new JTextField("10");
	    parse = new JTextField("10");
	    load.setEnabled(false);
	    parse.setEnabled(false);
	    JLabel loadlabel = new JLabel("Multiple     Load:");
	    JLabel parselabel = new JLabel("Parse:");
	    JPanel loadpanel = new JPanel(new BorderLayout());
	    JPanel parsepanel = new JPanel(new BorderLayout());
	    loadpanel.add(load, BorderLayout.CENTER);
	    loadpanel.add(loadlabel, BorderLayout.WEST);
	    parsepanel.add(parse, BorderLayout.CENTER);
	    parsepanel.add(parselabel, BorderLayout.WEST);
	    JPanel threadtextpanel = new JPanel(new BorderLayout());
	    loadparse = new JRadioButton();
	    threads.add(loadparse);
	    threadtextpanel.add(loadparse, BorderLayout.WEST);
	    threadtextpanel.add(loadpanel, BorderLayout.CENTER);
	    threadtextpanel.add(parsepanel, BorderLayout.EAST);
		threadpanel.add(threadstart, BorderLayout.NORTH);
		JPanel multipanel = new JPanel(new BorderLayout());
		multithread = new JTextField("10");
		multithread.setEnabled(false);
		multipanel.add(single, BorderLayout.NORTH);
		multipanel.add(multi, BorderLayout.WEST);
		multipanel.add(multithread, BorderLayout.CENTER);
		multipanel.add(threadtextpanel, BorderLayout.SOUTH);
	    threadpanel.add(multipanel, BorderLayout.WEST);
	    //print stream
		JLabel printlabel = new JLabel(" OUTPUT");
	    printlabel.setFont(new Font("SansSerif", Font.BOLD, 14));
	    printlabel.setForeground(Color.DARK_GRAY);
	    JPanel gui_panel = new JPanel(new BorderLayout());
	    my_gui = new JCheckBox("GUI");
	    my_gui.setSelected(true);
	    gui_panel.add(my_gui, BorderLayout.WEST);
	    JLabel gui_label = new JLabel(" update frequency");
	    gui_panel.add(gui_label, BorderLayout.EAST);
	    freq = new JTextField(Integer.toString(my_frequency));
	    gui_panel.add(freq, BorderLayout.CENTER);
	    console = new JCheckBox("Console");
	    file = new JCheckBox("File");
	    JPanel filepanel = new JPanel(new BorderLayout());
	    JPanel filechooser = new JPanel(new BorderLayout());
	    filepath = new JButton("Choose File");
	    filepath.setEnabled(false);
	    filechooser.add(filepath, BorderLayout.WEST);
	    filepanel.add(file, BorderLayout.WEST);
	    filepanel.add(filechooser, BorderLayout.CENTER);
	    final JLabel filelabel = new JLabel();
	    filechooser.add(filelabel, BorderLayout.CENTER);
	    JPanel printstreampanel = new JPanel(new BorderLayout());
	    JPanel printlabelpanel = new JPanel(new BorderLayout());
	    printlabelpanel.add(printlabel, BorderLayout.NORTH);
	    printlabelpanel.add(gui_panel, BorderLayout.WEST);
	    printstreampanel.add(printlabelpanel, BorderLayout.NORTH);
	    printstreampanel.add(console, BorderLayout.CENTER);
	    printstreampanel.add(filepanel, BorderLayout.SOUTH);
	    filepath.addActionListener(new ActionListener()
	      {
			public void actionPerformed(ActionEvent the_event) {
			    JFileChooser j = new JFileChooser();
			    FileNameExtensionFilter filter = new FileNameExtensionFilter(
			            "Text Files", "txt");
			        j.setFileFilter(filter);
			    int returnVal = j.showOpenDialog(null);
			    if(returnVal == JFileChooser.APPROVE_OPTION) {
			    	filelabel.setText(j.getSelectedFile().getName());
			    	filename = j.getSelectedFile();
			    }
			}
	      });
	    my_gui.addActionListener(new ActionListener()
	      {
			public void actionPerformed(ActionEvent the_event) {
				if(my_gui.isSelected()){
					freq.setEnabled(true);
				}else{
					freq.setEnabled(false);
				}
			}
	      });
	    
	    single.addActionListener(new ActionListener()
	      {
			public void actionPerformed(ActionEvent the_event) {
			    load.setEnabled(false);
			    parse.setEnabled(false);
			    multithread.setEnabled(false);  
			}
	      });
	    multi.addActionListener(new ActionListener()
	      {
			public void actionPerformed(ActionEvent the_event) {
			    loadparse.setEnabled(true);
			    if(!loadparse.isSelected()){
			    	multithread.setEnabled(true);  
				    load.setEnabled(false);
				    parse.setEnabled(false);
			    }else{
			    	multithread.setEnabled(false);
				    load.setEnabled(true);
				    parse.setEnabled(true);
			    }
			    
			}
	      });
	    loadparse.addActionListener(new ActionListener()
	      {
			public void actionPerformed(ActionEvent the_event) {
			    if (loadparse.isSelected()){
				    load.setEnabled(true);
				    parse.setEnabled(true);
				    multithread.setEnabled(false);
			    }else{
				    load.setEnabled(false);
				    parse.setEnabled(false);	
				    multithread.setEnabled(true);
				}
			}
	      });
	    file.addActionListener(new ActionListener()
	      {
			public void actionPerformed(ActionEvent the_event) {
			    if (file.isSelected()){
			    	filepath.setEnabled(true);
			    }else{
			    	filepath.setEnabled(false);
			    }
			}
	      });
	    my_start = new JButton("Start");
	    my_start.addActionListener(new ActionListener()
	      {
			public void actionPerformed(ActionEvent the_event) {
				startpressed = true;
				getData();
				stop();
			}
	      });
	    JPanel title = new JPanel( new BorderLayout());
	    JLabel linebreak = new JLabel("\n");
	    JLabel webcrawler = new JLabel("WEB CRAWLER");
	    webcrawler.setFont(new Font("SansSerif", Font.BOLD, 14));
	    webcrawler.setForeground(Color.DARK_GRAY);
	    title.add(webcrawler);
	    my_panel.add(linebreak);
	    my_panel.add(title);
		title.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
		printlabel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
		threadstart.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
	    my_panel.add(seedpanel);
	    my_panel.add(bannedpanel);
	    my_panel.add(searchtermspanel);
	    my_panel.add(maxpanel);
	    my_panel.add(threadpanel);
	    my_panel.add(printstreampanel);
	    JPanel startbutton = new JPanel(new BorderLayout());
	    startbutton.add(my_start, BorderLayout.WEST);
	    my_panel.add(startbutton);
	    my_frame.add(my_panel, BorderLayout.NORTH);
	    my_frame.setSize(new Dimension(500,425));
		my_frame.setTitle("Web Crawler");
		my_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		my_frame.setVisible(true);
	    my_frame.setResizable(false);
	}
	
	/**
	 * Gets the settings selected by the user.
	 * @return the settings the user selected in the GUI.
	 */
	public UserSettings getData() {
		while(!startpressed);
		String[] s = my_seeds_text.getText().split(", ");
		my_seeds.clear(); // need to remove default values.
		for (String line : my_seeds) System.out.println(line);
		for(int i = 0; i< s.length; i++){
			my_seeds.add(s[i]);
		}
		String[] b = my_banned_links_text.getText().split(", ");
		my_bannedlinks.clear(); // remove default terms, just use input
		for(int i = 0; i< b.length; i++){
			my_bannedlinks.add(b[i]);
		}
		String[] st = my_search_terms_text.getText().split(", ");
		my_searchterms.clear(); // remove default terms, just use input
		for(int i = 0; i< st.length; i++){
			my_searchterms.add(st[i]);
		}
		if(!single.isSelected()){
			if (multithread.isEnabled()){
				my_numthreads = new int[1];
				my_numthreads[0] = Integer.parseInt(multithread.getText());
			}else{
				my_numthreads = new int[2];
				my_numthreads[0] = Integer.parseInt(load.getText());
				my_numthreads[1] = Integer.parseInt(parse.getText());
			}
		}

		my_maxsites = Integer.parseInt(my_max_sites_text.getText());
		try {
			setStreams();
		} catch (FileNotFoundException the_error) {
			JOptionPane.showMessageDialog(my_frame, "Invalid File Specified, the program will not write to the file");	
		}
		//After start button is pressed, it will retrieve the input and set the UserSettings.
		UserSettings us = new UserSettings(my_seeds, my_bannedlinks, my_searchterms, my_printstreams, my_numthreads, my_gui.isSelected(), my_maxsites, my_frequency);
		
		return us;
	}

	/**
	 * Sets up the print streams.
	 * @throws FileNotFoundException if the file selected by the user is bad.
	 */
	private void setStreams() throws FileNotFoundException {
		if(my_gui.isSelected()){
			my_frequency = Integer.parseInt(freq.getText());
		}
		if (file.isSelected() && console.isSelected()) {
			my_printstreams = new PrintStream[2];
			my_printstreams[0]= new PrintStream(System.out);
			if (filename == null){
				JOptionPane.showMessageDialog(my_frame, "Invalid File Specified, the program will not write to the file");	
			}else{
				my_printstreams[1]= new PrintStream(new File(filepath.getText()));
			}
		} else if (file.isSelected() || console.isSelected()) {
			my_printstreams = new PrintStream[1];
			if (console.isSelected()) {
				my_printstreams[0]= new PrintStream(System.out);
			} else {
				if (filename == null){
					JOptionPane.showMessageDialog(my_frame, "Invalid File Specified, the program will not write to the file");	
				}else{
					my_printstreams[0] = new PrintStream(filename);
				}
			}
		}
	}

	/**
	 * Stops the gui.
	 */
	public void stop() {
		this.my_frame.dispose();
	}

}
